//
// Created by zhangrunquan on 20-4-27.
//


////#include "leveldb/db.h"
////#include <cstdio>
////#include <iostream>
////#include <stdio.h>
////#include <fstream>
////#include "test_data.h"
////
////enum ValueType {
////    kTypeDeletion = 0x0, kTypeValue = 0x1
////};
////enum RecordType {
////    // Zero is reserved for preallocated files
////            kZeroType = 0,
////
////    kFullType = 1,
////
////    // For fragments
////            kFirstType = 2,
////    kMiddleType = 3,
////    kLastType = 4
////};
////
////
////
////using namespace std;
////using namespace leveldb;
////
////
////void getVarint32Ptr(ifstream & fp,uint32_t& result){
////    uint8_t shift=0;
////    while(shift<29){
////        uint8_t data=0;
////        fp.read((char *)&data, sizeof(data));
////        bool bit=(bool)(data&0x80);
////        result|=(data&127)<<shift;
////        shift+=7;
////        if(!bit){
////            return;
////        }
////    }
////
////}
////
////
////
//////int main() {
////////    cout<< sizeof(uint32_t);
//////    string filepath="testdb/000032.log";
//////    ifstream fp;
//////    fp.open(filepath,ifstream::in);
////////
//////    while(fp.peek()!=EOF){
//////        //checksum
//////        uint32_t checksum=0;
//////        fp.read((char *)&checksum, sizeof(uint32_t));
//////        cout<<"checksum: "<<checksum<<"\t";
//////
//////        //length
//////        uint16_t recordLength=0;
//////        fp.read((char *)&recordLength,sizeof(uint16_t));
//////        cout<<"record length: "<<recordLength<<"\t";
//////
//////        //record type
//////        uint8_t recordType=0;
//////        fp.read((char *)&recordType,sizeof(recordType));
//////        switch (static_cast<RecordType >(recordType&0xff)){
//////            case kZeroType:
//////                cout<<"zerotype\t";
//////                exit(1);
//////            case kFirstType:
//////                cout<<"firsttype\t";
//////                break;
//////            case kFullType:
//////                cout<<"fulltype\t";
//////                break;
//////            case kMiddleType:
//////                cout<<"middletype\t";
//////                break;
//////            case kLastType:
//////                cout<<"lasttype";
//////                break;
//////            default:
//////                cout<<"error";
//////                exit(1);
//////        }
//////
//////        //seqnumber+entrynumber
//////        uint64_t tmp;
//////        fp.read((char *)&tmp, sizeof(uint64_t));
//////        fp.read((char *)&tmp, sizeof(uint32_t));
//////
//////
//////        //valuetype
//////        uint8_t valuetype=0;
//////        fp.read((char *)&valuetype,sizeof(valuetype));
//////
//////        //keysize+key
//////        uint32_t keysize=0;
//////        getVarint32Ptr(fp,keysize);
//////        cout<<"keysize: "<<keysize<<"\t";
//////
//////        char *key=new char[keysize];
//////        fp.read(key,keysize);
//////        cout<<"key: "<<key<<"\t";
//////        delete[](key);
//////
//////        switch (static_cast<ValueType >(valuetype&0xff)){
//////            case kTypeDeletion:
//////                cout<<"del\n";
//////                break;
//////            case kTypeValue:
//////                uint32_t valuesize=0;
//////                getVarint32Ptr(fp,valuesize);
//////                cout<<"valuesize: "<<valuesize<<"\t";
//////
//////                char *value=new char[valuesize];
//////                fp.read(value,valuesize);
//////                cout<<"value: "<<value<<"\n";
//////                break;
//////        }
//////
//////    }
////////    exit(0);
//////
//////
////////    DB* db = nullptr;
////////    Options op;
////////    op.create_if_missing = true;
////////    Status status = DB::Open(op, "testdb", &db);
////////    assert(status.ok());
////////    db->Put(WriteOptions(), "001", "leveldb");
////////    string s;
////////    db->Get(ReadOptions(), "001", &s);
////////    cout<<s<<endl;
////////
////////    db->Put(WriteOptions(), "002", "world");
////////    string s1;
////////    db->Delete(WriteOptions(), "002");
////////    db->Get(ReadOptions(), "002", &s1);
////////    cout<<s1<<endl;
////////
////////    delete db;
//////
////////
//////////  实验1
////////    DB* db = nullptr;
////////    Options op;
////////    op.create_if_missing = true;
////////    Status status = DB::Open(op, "testdb4", &db);
////////    assert(status.ok());
////////
////////
////////
////////    //first read
////////    freopen("./test/input1","r",stdin);
////////
////////    string number,grade;
////////    while(cin>>number>>grade){
////////        db->Put(WriteOptions(),number,grade);
////////    }
////////
////////    fclose(stdin);
////////    cin.clear();
////////
////////    db->Delete(WriteOptions(), "002");
//////
//////
//////
////////    //get snapshot
////////    leveldb::ReadOptions options;
////////    options.snapshot = db->GetSnapshot();
////////
////////
////////    //second read
////////    freopen("./test/input2","r",stdin);
////////
////////    while(cin>>number>>grade){
////////        db->Put(WriteOptions(),number,grade);
////////    }
////////
////////    fclose(stdin);
////////    cin.clear();
////////
////////    //write
////////    freopen("./test/output","w",stdout);
////////
////////    leveldb::Iterator* it1 = db->NewIterator(options);
////////    leveldb::Iterator* it2 = db->NewIterator(ReadOptions());
////////
////////    it1->SeekToFirst();
////////    it2->SeekToFirst();
////////    for(;it1->Valid(),it2->Valid();it1->Next(),it2->Next()){
////////        cout<<it1->key().ToString()<<" "<<it1->value().ToString()<<" "<<it2->value().ToString()<<endl;
////////    }
////////
////////    delete it1;
////////    delete it2;
////////    db->ReleaseSnapshot(options.snapshot);
//////
////////    delete db;
//////    return 0;
//////}
////
////int main(){
//////    makeTestData();
////
////}
//
//#include "leveldb/db.h"
//#include "test_data.h"
//#include <iostream>
//#include <cstdio>
//#include <fstream>
//
//using namespace std;
//enum RecordType {
//    kZeroType = 0x0,
//    kFirstType = 0x2,
//    kMiddleType = 0x3,
//    kLastType = 0x4
//};
//
//enum ValueType {
//    typedelete = 0x0,
//    typevalue = 0x1
//};
//
//const int kBlockSize = 32768;
//
//const int kHeaderSize = 4 + 2 + 1;
//
//int getVarint32Ptr(ifstream *fp,uint32_t* keylength){
//    uint32_t result=0;
//    int bytenumber=0;
//    int cnt=0;
//    while(cnt<35){
//        uint64_t temp=0;
//        fp->read((char *)&temp, sizeof(uint8_t));
//        if(temp &128){
//            result|=(temp&127)<<cnt;
//            bytenumber+=1;
//        }else{
//            result|=(temp<<cnt);
//            *keylength=result;
//            bytenumber+=1;
//            return bytenumber;
//        }
//        cnt+=7;
//    }
//}
//
//int getVarint32Ptr(bool *finish,uint16_t* leftlength,ifstream * fp,uint32_t *keylength){
//    uint32_t result=0;
//    int bytenumber=0;
//    int cnt=0;
//    while(cnt<35){
//        uint64_t temp=0;
//        fp->read((char *)&temp, sizeof(uint8_t));
//        if(temp &128){
//            result|=(temp&127)<<cnt;
//            bytenumber+=1;
//            *leftlength-=1;
//            if(*leftlength==0){
//                *finish=0;
//                *keylength=result;
//                return bytenumber;
//            }
//        }else{
//            result|=(temp<<cnt);
//            *keylength=result;
//            bytenumber+=1;
//            *leftlength-=1;
//            *finish=1;
//            return bytenumber;
//        }
//        cnt+=7;
//    }
//}
//
//int outputLog(const string& filename){
////    string filename = "testdb1/000003.log";
//    ifstream fp;
//    fp.open(filename, ifstream::in);
//    bool fg[8] = {0};
//    uint64_t seqnumber = 0;
//    uint32_t entrynumber = 0;
//    uint8_t valuetype;
//    uint32_t keylength = 0;
//    uint32_t valuelength = 0;
//    uint16_t usedlength = 0;
//    int bytenumber = 0;
//    int leftbyte = kBlockSize;
//    while (fp.peek() != EOF) {
//        char *tmp = new char[kHeaderSize];
//        if (leftbyte < kHeaderSize) {
//            fp.read(tmp, leftbyte);
//            cout << "padding " << leftbyte << endl;
//        }
//
//        uint32_t header = 0;
//        fp.read((char *) &header, sizeof(uint32_t));
//        cout << "checksum: " << header << endl;
//
//        uint16_t length = 0;
//        fp.read((char *) &length, sizeof(uint16_t));
//        cout << "length: " << length << endl;
//        uint16_t leftlength = length;
//
//
//        uint8_t recordtype = 0;
//        fp.read((char *) &recordtype, sizeof(recordtype));
//        leftbyte -= kHeaderSize;
//        RecordType rt = static_cast<RecordType >(recordtype & 0xff);
//
//
//        if (rt == 0) {
//            cout << "kZeroType\n";
//            continue;
//        }
//        if (rt == 1) {
//            cout << "kFullType\n";
//            leftbyte -= length;
//
//            fp.read((char *) &seqnumber, sizeof(uint64_t));
//            cout << "seqnumber: " << seqnumber << endl;
//            leftlength -= 8;
//
//            fp.read((char *) &entrynumber, sizeof(uint32_t));
//            cout << "blocknumber: " << entrynumber << endl;
//            leftlength -= 4;
//
//            fp.read((char *) &valuetype, sizeof(uint8_t));
//            leftlength -= 1;
//
//            bytenumber = getVarint32Ptr(&fp, &keylength);
//            cout << "keylength: " << keylength << endl;
//            leftlength -= bytenumber;
//            char *key = new char[keylength];
//            fp.read(key, keylength);
//
//            cout << "key: " << key << endl;
//            leftlength -= keylength;
//            keylength = 0;
//
//            switch (static_cast<ValueType >(valuetype & 0xff)) {
//                case typedelete:
//                    cout << "del\n";
//                    break;
//                case typevalue:
//                    bytenumber = getVarint32Ptr(&fp, &valuelength);
//                    cout << "valuelength: " << valuelength << endl;
//                    leftlength -= bytenumber;
//                    char *value = new char[valuelength];
//                    fp.read(value, valuelength);
//                    cout << "value: " << value << "\n\n";
//                    leftlength-=valuelength;
//                    valuelength = 0;
//                    break;
//            }
//            bytenumber = 0;
//            if (leftlength != 0) {
//                cout << "Error1!\n\n";
//            } else {
//                continue;
//            }
//            cout << endl;
//        }
//        if (rt == 2 || rt == 3 || rt == 4) {
//            if (rt == 2) {
//                cout << "kFirstType\n";
//                leftbyte = kBlockSize;
//                fg[1] = 1;
//            }
//            if (rt == 3) {
//                cout << "kMiddleType\n";
//                leftbyte = kBlockSize;
//            }
//            if (rt == 4) {
//                cout << "kLastType\n";
//                leftbyte -= length;
//            }
//            int deal = 0;
//            for (int i = 1; i < 8; i++) {
//                if (fg[i] == 1) {
//                    deal = i;
//                    break;
//                }
//            }
//            switch (deal) {
//                case 1://seqnumber
//                    if (leftlength >= (8 - usedlength)) {//begin or continue
//                        uint64_t temp = 0;
//                        fp.read((char *) &temp, 8 - usedlength);
//                        seqnumber |= temp << (usedlength * 8);
//                        cout << "seqnumber: " << seqnumber << "\n";
//                        leftlength -= 8 - usedlength;
//                        usedlength = 0;
//                        fg[1] = 0;
//                        if (leftlength == 0) {
//                            fg[2] = 1;
//                            continue;
//                        }
//                    } else {//cut at seqnumber
//                        fp.read((char *) &seqnumber, leftlength);
//                        usedlength += leftlength;
//                        fg[1] = 1;
//                        leftlength = 0;
//                        continue;
//                    }
//                case 2://entrynumber
//                    if (leftlength >= (4 - usedlength)) {
//                        uint32_t temp = 0;
//                        fp.read((char *) &temp, 4 - usedlength);
//                        entrynumber |= temp << (usedlength * 8);
//                        cout << "entrynumber: " << entrynumber << "\n";
//                        leftlength -= 4 - usedlength;
//                        usedlength=0;
//                        fg[2]=0;
//                        if(leftlength==0){
//                            fg[3]=1;
//                            continue;
//                        }
//                    }else{
//                        fp.read((char*)&entrynumber,leftlength);
//                        usedlength+=leftlength;
//                        fg[2]=1;
//                        leftlength=0;
//                        continue;
//                    }
//                case 3://valuetype
//                    if(leftlength>=1){
//                        fp.read((char*)&valuetype, sizeof(uint8_t));
//                        leftlength-=1;
//                        fg[3]=0;
//                        if(leftlength==0){
//                            fg[4]=1;
//                            continue;
//                        }
//                    } else{
//                        fg[3]=1;
//                        continue;
//                    }
//                case 4://keylength
//                    if (leftlength>=(5-bytenumber)){
//                        uint32_t temp =0;
//                        int bynumber=getVarint32Ptr(&fp,&temp);
//                        keylength|=temp<<((bynumber-1)*7);
//                        cout<<"keylength: "<< keylength<<endl;
//                        leftlength-=bynumber;
//                        bytenumber=0;
//                        fg[4]=0;
//                        if(leftlength==0){
//                            fg[5]=1;
//                            continue;
//                        }
//                    } else{
//                        bool finish=0;
//                        bytenumber=getVarint32Ptr(&finish,&leftlength,&fp,&keylength);
//                        if(!finish){
//                            if(leftlength!=0){
//                                cout<<"Error2!\n";
//                                return 0;
//                            }
//                            fg[4]=0;
//                            continue;
//                        }else{
//                            bytenumber=0;
//                            fg[4]=0;
//                            if(leftlength==0){
//                                fg[5]=1;
//                                continue;
//                            }
//                        }
//                    }
//                case 5://key
//                    if(keylength>usedlength){
//                        int left=keylength-usedlength;
//                        if(leftlength>=left){
//                            char * key=new char[left];
//                            fp.read(key,left);
//                            cout<< "keylength: "<< left<<"key:"<< key<<"\n";
//                            leftlength-=left;
//                            usedlength=0;
//                            keylength=0;
//                            fg[5]=0;
//                            if(leftlength==0){
//                                fg[6]=1;
//                                continue;
//                            }
//                        }
//                    }else{
//                        char * key=new char[leftlength];
//                        fp.read(key,leftlength);
//                        cout<< "keylength: "<<leftlength<< "key: "<<key<< "\n";
//                        usedlength+=leftlength;
//                        fg[5]=1;
//                        leftlength=0;
//                        continue;
//                    }
//                case 6://vlength
//                    if(leftlength>=(5-bytenumber)){
//                        uint32_t temp=0;
//                        int bynumber=getVarint32Ptr(&fp,&temp);
//                        valuelength|=temp<<(bytenumber*7);
//                        cout<<"valuelength: "<< valuelength<<endl;
//                        bytenumber=0;
//                        leftlength-=bynumber;
//                        fg[6]=0;
//                        if(leftlength==0){
//                            fg[7]=1;
//                            continue;
//                        }
//                    }else{
//                        bool finish=0;
//                        bytenumber=getVarint32Ptr(&finish,&leftlength,&fp,&valuelength);
//                        if(!finish){
//                            if(leftlength!=0){
//                                cout<< "Error3!\n";
//                                return 0;
//                            }
//                            fg[6]=1;
//                            continue;
//                        }else{
//                            bytenumber=0;
//                            fg[6]=0;
//                            if(leftlength==0){
//                                fg[7]=1;
//                                continue;
//                            }
//                        }
//                    }
//                case 7://value
//                    if (valuelength>usedlength){
//                        int left=valuelength-usedlength;
//                        if(leftlength>=left){
//                            char * value=new char[left];
//                            fp.read(value,left);
//                            cout<< "valuelength: "<<left<< " value: "<<value<<"\n\n";
//                            fg[7]=0;
//                            leftlength-=left;
//                            usedlength=0;
//                            valuelength=0;
//                        } else{
//                            char * value=new char[leftlength];
//                            fp.read(value,leftlength);
//                            cout<< "valuelength: "<<leftlength<< " value: "<<value<<"\n\n";
//                            usedlength+=leftlength;
//                            fg[7]=1;
//                            leftlength=0;
//                            continue;
//                        }
//                    }else continue;
//                default:
//                    if (valuetype==0){
//                        cout<<"del\n";
//                    }
//            }
//        }
//    }
//    fp.close();
//}
//
//int main() {
////    string filename = "testdb/";
////    string filename = "testdb1/000003.log";
//    cout<<"test1\n";
//    outputLog("testdb1/000003.log");
//
//    cout<<"test2\n";
//    outputLog("testdb2/000003.log");
//    cout<<"test3\n";
//    outputLog("testdb3/000003.log");
//    cout<<"test4\n";
//    outputLog("testdb4/000003.log");
//    cout<<"test5\n";
//    outputLog("testdb5/000003.log");
//
//    return 0;
//}
//
////int main(){
////    makeTestData();
////}
